package com.cameronyule.echonest.api
{
	import com.cameronyule.echonest.EchoNest;
	import com.cameronyule.echonest.errors.EchonestError;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.HTTPStatusEvent;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;
	import flash.net.URLVariables;

	import com.cameronyule.echonest.events.EchonestResponseEvent;

	public class EchonestRequest extends EventDispatcher
	{
		private var _loader:URLLoader;
		
		/**
		 * Send the API call to Echo Nest.
		 * 
		 * @param method		The API method to call
		 * @param parameters	Parameters for the API method
		 * @param requestMethod	HTTP method to be used for the call. Optional, defaults to GET.
		 **/
		public function EchonestRequest(method:String, parameters:Object, requestMethod:String = '')
		{
			createLoader();
			var request:URLRequest = createRequest(method, parameters, requestMethod);

            try
            {
                _loader.load(request);
            }
            catch (error:Error)
            {
                throw new EchonestError('Unable to load requested document.');
            }
		}
		
		private function createLoader():void
		{
			_loader = new URLLoader();
			_loader.addEventListener(Event.COMPLETE, completeHandler);
			_loader.addEventListener(Event.OPEN, openHandler);
			_loader.addEventListener(ProgressEvent.PROGRESS, progressHandler);
			_loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
			_loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
			_loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
		}
		
		private function createRequest(method:String, parameters:Object, requestMethod:String):URLRequest
		{
        	var request:URLRequest = new URLRequest(EchoNest.API_URL + method);            
            if (requestMethod == '') requestMethod = URLRequestMethod.GET;
            request.method = requestMethod;
            
            var variables:URLVariables = new URLVariables();            
            for (var parameter:String in parameters)
            {
            	variables[parameter] = parameters[parameter];	
            }            
            request.data = variables;
            
            return request;
		}
		
        private function completeHandler(event:Event):void
        {            
            var response:XML = XML(_loader.data);
            dispatchEvent(new EchonestResponseEvent(EchonestResponseEvent.RESPONSE, response));
            destroy();
        }
        
        private function openHandler(event:Event):void
        {
//            trace("openHandler: " + event);
        }
        
        private function progressHandler(event:ProgressEvent):void
        {
//            trace("progressHandler loaded:" + event.bytesLoaded + " total: " + event.bytesTotal);
        }
        
        private function securityErrorHandler(event:SecurityErrorEvent):void
        {
            destroy();
            throw new EchonestError('SecurityErrorEvent ' + event.text);
        }
        
        private function httpStatusHandler(event:HTTPStatusEvent):void
        {
//            trace("httpStatusHandler: " + event);
        }
        
        private function ioErrorHandler(event:IOErrorEvent):void
        {
        	destroy();
			throw new EchonestError('IOErrorEvent ' + event.text);
        } 
        
        private function destroy():void
        {
			_loader.close();
			_loader.removeEventListener(Event.COMPLETE, completeHandler);
			_loader.removeEventListener(Event.OPEN, openHandler);
			_loader.removeEventListener(ProgressEvent.PROGRESS, progressHandler);
			_loader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
			_loader.removeEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
			_loader.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
        }       
	}
}